package com.example.mysql.学习笔记.高级.数据库的优化之索引.性能分析工具;

public class 分析查询语句EXPLAIN {
}

/**
 * 执行计划   并未执行
 * 定位了查询慢的SQL之后,我们就可以使用EXPLAIN或DESCRIBE工具做针对性的分析查询语句。
 * DESCRIBE语句的使用方法与EXPLAIN语句是一样的， 并且分析结果也是一样的。
 * MySQL中有专门负责优化 SELECT下语句的优化器模块,
 * 主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供它认为最优的执行计划
 * (他认为最优的数据检索方式，但不见得是DBA认为是最优的，这部分最耗费时间)。
 * 这个执行计划展示了接下来具体执行查询的方式，比如多表连接的顺序是什么，
 * 对于每个表采用什么访问方法来具体执行查询等等。
 * MySQL为我们提供了EXPLAIN语句来帮助我们查看某个查询语句的具体执行计划，
 * 大家看懂EXPLAIN语句的各个输出项，可以有针对性的提升我们查询语句的性能。
 *
 * 1.能做什么?
 * ●表的读取顺序
 * ●数据读取操作的操作类型
 * ●哪些索引可以使用
 * ●哪些索弓|被实际使用
 * ●表之间的引用
 * ●每张表有多少行被优化器查询
 *
 * ●MySQL 5.6.3以前只能EXPLAIN SELECT; MYSQL 5.6.3以后就可以EXPLAIN SELECT, UPDATE， DELETE
 * ●在5.7以前的版本中，想要显示partitions需要使用explain partitions命令;
 * 想要显示filtered需要使用explain extended 命令。
 * 在5.7版本后,默认explain直接显示partitions和filtered中的信息。
 *
 * 注意:执行EXPLAIN时并没有真正的执行该后面的语句,因此可以安全的查看执行计划。
 *  EXPLAIN语句输出的各个列的作用如下:
 *
 * 列名                   描述
 * id                    在一个大的查询语句中每个SELECT关键字都对应一个唯一的id
 * select_type          SELECT关键字对应的那个查询的类型
 * table                 名
 * partitions            匹配的分区信息
 * type                  针对单表的访问方法
 * possible_keys         可能用到的索引
 * key                   实际上使用的索引
 * key_len               实际使用到的索引长度
 * ref                   当使用索引列等值查询时，与索引列进行等值匹配的对象信息
 * rows                  预估的需要读取的记录条数
 * filtered              某个表经过搜索条件过滤后剩余记录条数的百分比
 * Extra                 一些额外的信息
 *
 */

/**
 * table   涉及的表   一个表一列   可能存在临时表  表示当前语句是对哪一个表进行
 *         涉及多表时  第一列 是驱动表  其他 被驱动表    < derived1 >由id=1的表 是派生类的表
 *
 * id      在一个大的查询语句中每个SELECT关键字都对应一个唯一的id
 *         即 一个SELECT  一个id（从1开始）
 *         也有可能特殊情况  比如可能两个 SELECT 内部进行优化 优化成了1个
 *         UNION（联合）   进行满链接    会出现临时表
 *         即出现一个id=null  table=(一个自定义的 内涵哪几个表连接)
 *      小结:
 *      ●id如果相同，可以认为是一组， 从上往下顺序执行
 *      ●在所有组中，id值越大，优先级越高，越先执行
 *      ●关注点:  id号每个号码，表示一趟独立的查询, -个sql的查询趟数越少越好
 *
 */

/**
 * select_type   当前查询 扮演了一个什么角色
 *   一条大的查询语句里边可以包含若干个SELECT关键字，每个SELECT关键字代表着一个小的查询语句 ，
 *   而每个SELECT关键字的FROM子句中都可以包含若干张表(这些表用来做连接查询)，
 *
 * SIMPLE (简单的)查询语句中不包含 UNION 或者 子查询 的查询都算作是SIMPLE  子链接也是SIMPLE.
 * #对于包含UNION.或者UNION ALL:或者子查询的大查询来说，它是由几个小查询组成的，
 *  其中最左边的查询的 select_type 值就是 PRIMARY （重要的）
 * #对于包含UNION、或者、UNION ALL"的大查询来说，它是由几个小查询组成的，
 *  其中除了最左边的那个小以外，其余的小查询的select_type值就是 UNION （联合）
 * #MySQL"选择使用临时表来完成、UNION、查询的去重工作，
 *  针对该临时表的查询的 select_type 就是 UNION RESULT （联合结果）
 *
 *
 * 子查询:
 * SUBQUERY (子查询)            不相关子查询
 *   如果包含子查询的查询语句不能够转为对应的 semi-join (半连接)的形式，并且该子查询是不相关子查询。
 *   该子查询的第一个、SELECT:关键字代表的那个查询的 select_type 就是 SUBQUERY
 * DEPENDENT (依赖的) SUBQUERY (子查询)    相关子查询
 *   如果包含子查询的查询语句不能够转为对应的 semi-join 的形式，并且该子查询是相关子查询,
 *   则该子查询的第一个SELECT关键字代表的那个查询的、select_type、就是、DEPENDENT SUBQUERY
 *
 * DEPENDENT  UNION   依赖 联合     子查询的内部查询都依赖最外层的查询
 * DERIVED 衍生    派生类的表  即这个表是由某个表的一些字段 经过计算得到的字段
 *
 * MATERIALIZED
 * #当查询优化器在执行包含子查询的语句时，选择将子查询物化之后与外层查询进行连接查询时，
 * #该子查询对应的、select_type、属性就是、MATERIALIZED'
 * EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 |FROM s2); 子查询被转为了物化表
 *
 */

/**
 * 4. partition (略):匹配的分区信息.    比如把id<100放在第一分区  其他第二分区  就会显示  第几分区
 * ●代表分区表中的命中情况，非分区表,该项为NULL。
 * -般情况下我们的查询语句的执行计划的partitions列的值都是NULL。
 */
/**
 * 5. type★       针对单表的访问方法 索引使用情况
 * 执行计划的-条记录就代表着MySQL对某个表的执行查询时的访问方法，又称“访问类型”，其中的type列就表明
 * 了这个访问方法是啥，是较为重要的一一个指标。比如，看到type列的值是ref ,表明MySQL即将使用ref访问
 * 方法来执行对s1表的查询。
 * 完整的访问方法如下:
 * system  const, eq_ref， ref，fulltext，ref_or_null， index_merge ,
 * unique_subquery，index_subquery，range ，index ，ALL。
 *
 * system
 * 当表中、只有一条记录并且该表使用的存储引擎的统计数据是精确的，
 * 比如 MyISAM （表的总数据数  单独用一个数据保存 COUNT(*)）、Memory,
 *  那么对该表的访问方法就是、system
 * const  主键(唯一索引也行)精确查找某一条数据
 * eq_ref 在连接查询时，如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的
 *        和const区别是  一个是直接查询 一个是根据另一个查询等值连接
 * ref            普通索引(不唯一  不为空)  等值查询
 * ref_or_null    普通索引(不唯一)  等值查询但存在为空
 * index_merge    两个等值查询 普通索引 用OR连接     AND连接是ref
 * unique_subquery    针对包含IN的子查询  如果自动转换为 EXISTS 子查询
 *                    并且子查询用到主键进行等值匹配
 * range          普通索引  范围查询    阿里巴巴手册最起码要求
 * index  当我们可以使用索引覆盖，但需要扫描全部的索引记录时，该表的访问方法就是、index.
 * ALL     全表查询  存在隐式转换也会出现
 *
 *
 */

/**
 * 6. possible_keys 和 key
 * 在EXPLAIN语句输出的执行计划中，possible_keys列表示在某个查询语句中，
 * 对某个表执行单表查询时可能用到的索引有哪些。
 * 一般查询涉及到的字段上若存在索引，则该索引将被列出,但不一定被查询使用。
 * key 列表示实际用到的索引有哪些,如果为NULL,则没有使用索引。
 *
 * possible_keys  一般语句中用到的字段 有相关的索引都会出现
 *  key           一般情况下是possible_keys子集
 *                如果出现  经过系统自己优化 出现了索引  也会显示
 *
 */
/**
 * 7.key_len
 * key_len:实际使用到的索引长度(即:字节数)
 * 带你检查、是否充分的利用上了索引、值越大越好、主要针对于联合索引，有一定的参考意义。
 *
 * 如  查询一个等值的 VARCHAR(100) 类型 会出现303 300(汉字占3字节)+1(非空)+2(变长字节记录长度)
 *     INT   5   4（INT 是4字节  1非空）
 *
 *  UTF8 一个字符 3字节
 *  gbk   2
 *  latin1  1
 *
 *
 */

/**
 * 8.ref  当使用索引列等值查询时，与索引列进行等值匹配的对象信息是 func
 *
 *
 * 9.rows:预估的需要读取的记录条数   越小  说明读取少量数据就可以把结果返回
 *
 * 10.filtered  某个表经过搜索条件过滤后剩余记录条数的 百分比
 *               比如  and操作 左边  筛选了200条  filtered=10  表示在经过右边的删选
 *
 */

/**
 * 11.Extra  一些额外的信息
 *
 * 顾名思义，Extra 列是用来说明--些额外信息的，包含不适合在其他列中显示但十分重要的额外信息。
 * 我们可以通过这些额外信息来更准确的理解MySQL到底将如何执行给定的查询语句。
 * MySQL 提供的额外信息有好几十个，
 * 我们就不一个一个介绍了，所以我们只挑比较重要的额外信息介绍给大家。
 *
 * NO tables used     当查询语句的没有、FROM子句时将会提示该额外信息
 * Impossible WHERE    where 条件不可能成立 如 where 1！=1
 * Using where       常规全表的where查询  或者 有索引也有非索引的where
 * null              索引的where查询
 *
 * 当查询列表处有、MIN  MAX、聚合函数，
 * no matching min/nax row  但是并没有符合 WHERE 子句中的搜索条件的记录时，将会提示该额外信息
 * Select tables optimized away 有符合 WHERE 子句中的搜索条件的记录时，将会提示该额外信息
 * Using index  当我们的查询列表以及搜索条件中只包含属于某个索引的列，也就是在可以
 *              使用覆盖索引的情况下，在 Extra 列将会提示该额外信息。
 *              比方说下边这个查询中只需要用到idx_key1 、而   不需要回表操作
 *    回表操作   当使用索引查寻的时候  只返回索引部分 不进行对聚簇索引  二次回表
 *              因为非聚簇索引存的只有主键和索引字段  其他字段如果需要的话  需要再从主键索引中再次查询
 *              回表操作其实是一个随机I/0，比较耗时
 * Using index condition    使用索引列  但是没用到索引
 * Zero limit   当我们的  LIMIT 子句的参数为'0‘时，表示压根儿不打算从表中读出任何记录，将会提示该额外信息
 *Using filesort 使用文件排序  没使用索引进行排序查找
 * Using temporary  使用了临时表  “并不是一个好的征兆，因为建立与维护临时表聚付出很大成本的,
 *                 最好能使用索引来替代掉使用临时表
 *
 */

/**
 *12.小结
 * ●EXPLAIN不考虑各种Cache
 * ●EXPLAIN不能显示MySQL在执行查询时所作的优化工作
 * ●EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
 * ●部分统计信息是估算的，并非精确值
 *
 *
 */